package org.dromara.demo.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.deepoove.poi.XWPFTemplate;
import com.deepoove.poi.config.Configure;
import com.deepoove.poi.plugin.table.LoopRowTableRenderPolicy;
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import org.apache.commons.io.FileUtils;
import org.dromara.common.core.exception.ServiceException;
import org.dromara.common.core.utils.MapstructUtils;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.demo.domain.JsExample;
import org.dromara.demo.domain.JsSuite;
import org.dromara.demo.domain.JsSuiteBasicVar;
import org.dromara.demo.domain.bo.JsSuiteBo;
import org.dromara.demo.domain.vo.JsSuiteVo;
import org.dromara.demo.mapper.JsSuiteBasicVarMapper;
import org.dromara.demo.mapper.JsSuiteMapper;
import org.dromara.demo.service.IJsSuiteBasicVarService;
import org.dromara.demo.service.IJsSuiteService;
import org.dromara.demo.util.FileTransUtils;
import org.springframework.stereotype.Service;

import java.io.*;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.*;

/**
 * 用例执行Service业务层处理
 *
 * @author zhu
 * @date 2024-12-31
 */
@RequiredArgsConstructor
@Service
public class JsSuiteServiceImpl implements IJsSuiteService {

    private final JsSuiteMapper baseMapper;

    private final JsSuiteBasicVarMapper jsSuiteBasicVarMapper;

    private final IJsSuiteBasicVarService jsSuiteBasicVarService;

    /**
     * 查询用例执行
     *
     * @param id 主键
     * @return 用例执行
     */
    @Override
    public JsSuiteVo queryById(Long id){
        return baseMapper.selectVoById(id);
    }

    /**
     * 分页查询用例执行列表
     *
     * @param bo        查询条件
     * @param pageQuery 分页参数
     * @return 用例执行分页列表
     */
    @Override
    public TableDataInfo<JsSuiteVo> queryPageList(JsSuiteBo bo, PageQuery pageQuery) {
        LambdaQueryWrapper<JsSuite> lqw = buildQueryWrapper(bo);
        Page<JsSuiteVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
        return TableDataInfo.build(result);
    }

    /**
     * 查询符合条件的用例执行列表
     *
     * @param bo 查询条件
     * @return 用例执行列表
     */
    @Override
    public List<JsSuiteVo> queryList(JsSuiteBo bo) {
        LambdaQueryWrapper<JsSuite> lqw = buildQueryWrapper(bo);
        return baseMapper.selectVoList(lqw);
    }

    private LambdaQueryWrapper<JsSuite> buildQueryWrapper(JsSuiteBo bo) {
        Map<String, Object> params = bo.getParams();
        LambdaQueryWrapper<JsSuite> lqw = Wrappers.lambdaQuery();
        lqw.eq(bo.getExampleId() != null, JsSuite::getExampleId, bo.getExampleId());
        lqw.eq(StringUtils.isNotBlank(bo.getStatus()), JsSuite::getStatus, bo.getStatus());
        lqw.like(StringUtils.isNotBlank(bo.getName()), JsSuite::getName, bo.getName());
        return lqw;
    }

    /**
     * 新增用例执行
     *
     * @param bo 用例执行
     * @return 是否新增成功
     */
    @Override
    public Boolean insertByBo(JsSuiteBo bo) {
        JsSuite add = MapstructUtils.convert(bo, JsSuite.class);
        validEntityBeforeSave(add);
        boolean flag = baseMapper.insert(add) > 0;
        if (flag) {
            bo.setId(add.getId());
            JsSuiteBasicVar jsSuiteBasicVar = new JsSuiteBasicVar();
            jsSuiteBasicVar.setSuiteId(bo.getId());
            jsSuiteBasicVar.setExampleIds(bo.getExampleId());
            jsSuiteBasicVarMapper.insert(jsSuiteBasicVar);
        }
        return flag;
    }

    /**
     * 修改用例执行
     *
     * @param bo 用例执行
     * @return 是否修改成功
     */
    @Override
    public Boolean updateByBo(JsSuiteBo bo) {
        JsSuite update = MapstructUtils.convert(bo, JsSuite.class);
        validEntityBeforeSave(update);
        boolean b = baseMapper.updateById(update) > 0;

        jsSuiteBasicVarService.updateBySuiteId(bo.getId(), bo.getExampleId());
        return b;
    }

    /**
     * 保存前的数据校验
     */
    private void validEntityBeforeSave(JsSuite entity){
        //TODO 做一些数据校验,如唯一约束
    }

    /**
     * 校验并批量删除用例执行信息
     *
     * @param ids     待删除的主键集合
     * @param isValid 是否进行有效性校验
     * @return 是否删除成功
     */
    @Override
    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
        if(isValid){
            if(isValid){
                // 做一些业务上的校验,判断是否需要校验
                List<JsSuite> list = baseMapper.selectByIds(ids);
                if (list.size() != ids.size()) {
                    throw new ServiceException("sys.no.delete.permission");
                }
            }
        }
        return baseMapper.deleteByIds(ids) > 0;
    }

    @Override
    public void exportReport(JsSuiteBo bo, HttpServletResponse response) {
        Map<String, Object> params = new HashMap<>();
        params.put("ProjectNo","1");
        params.put("ProjectName","111");
        params.put("TesterName","张三");
        params.put("Department","测试部");
        String fileName = System.currentTimeMillis() + ".docx";
        String tmpPath = "D:\\" + fileName;
        String path = copyTempFile("word/result.docx");
        String PDFName = null;
        try {
            //4.编译模板，渲染数据
            LoopRowTableRenderPolicy hackLoopTableRenderPolicy = new LoopRowTableRenderPolicy();
            Configure config = Configure.builder().bind("byWordVoList", hackLoopTableRenderPolicy).bind("originalVoList", hackLoopTableRenderPolicy).build();
            XWPFTemplate template = XWPFTemplate.compile(path, config).render(params);
            //5.写入到指定目录位置
            FileOutputStream fos = new FileOutputStream(tmpPath);
            template.write(fos);
            fos.flush();
            fos.close();
            template.close();
            PDFName = "D:\\"+System.currentTimeMillis() + ".pdf";
            FileTransUtils.doc2pdf(new File(tmpPath), PDFName);
            down(response, PDFName, PDFName);
            //6.提供下载
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            //7.删除临时文件
            File file = new File(tmpPath);
            file.delete();
            File copyFile = new File(PDFName);
            copyFile.delete();
        }
    }
    /**
     * 下载文件
     * @param response 相应
     * @param data 数据
     * @param fileName 文件名
     */
    private void generateFile(HttpServletResponse response, byte[] data, String fileName) {
        response.setHeader("content-Type", "application/octet-stream");
        response.setCharacterEncoding("utf-8");
        response.setHeader("Content-disposition", "attachment;filename=" + fileName);
        try {
            response.getOutputStream().write(data);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                response.getOutputStream().close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    private String copyTempFile(String templeFilePath) {
        InputStream inputStream = getClass().getClassLoader().getResourceAsStream(templeFilePath);
        String tempFileName = System.getProperty("user.home") + "/" + "1.docx";
        File tempFile = new File(tempFileName);
        try {
            FileUtils.copyInputStreamToFile(inputStream, tempFile);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        return tempFile.getPath();
    }

    /**
     * 百分号编码工具方法
     *
     * @param s 需要百分号编码的字符串
     * @return 百分号编码后的字符串
     */
    public static String percentEncode(String s) throws UnsupportedEncodingException {
        String encode = URLEncoder.encode(s, StandardCharsets.UTF_8.toString());
        return encode.replaceAll("\\+", "%20");
    }

    private void down(HttpServletResponse response, String filePath, String realFileName) throws UnsupportedEncodingException {
        String percentEncodedFileName = null;
        percentEncodedFileName = percentEncode(realFileName);
        StringBuilder contentDispositionValue = new StringBuilder();
        contentDispositionValue.append("attachment; filename=").append(percentEncodedFileName).append(";").append("filename*=").append("utf-8''").append(percentEncodedFileName);

        response.addHeader("Access-Control-Allow-Origin", "*");
        response.addHeader("Access-Control-Expose-Headers", "Content-Disposition,download-filename");
        response.setHeader("Content-disposition", contentDispositionValue.toString());
        response.setHeader("download-filename", percentEncodedFileName);
        try (BufferedInputStream bis = new BufferedInputStream(new FileInputStream(filePath));
             // 输出流
             BufferedOutputStream bos = new BufferedOutputStream(response.getOutputStream());) {
            byte[] buff = new byte[1024];
            int len = 0;
            while ((len = bis.read(buff)) > 0) {
                bos.write(buff, 0, len);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}
